home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 September / macformat-041.iso / mac / Shareware City / Graphics / MacSPD / Sources / shells.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-30  |  6.5 KB  |  238 lines  |  [TEXT/MMCC]

  1. /*
  2.  * shells.c - Creates a shell using Pickover's generation method (see IEEE
  3.  *     CG&A November 1989).  One light source.  This thing tends to bring ray
  4.  *     tracers to their knees (lots of overlapping primitives, many quite
  5.  *     tiny) - it's meant as a study of a realistic yet pathological database.
  6.  *
  7.  *     There are various additional characteristics which can be diddled with
  8.  *     for different shell shapes (most pretty unrealistic, but there you go).
  9.  *     See Pickover's article for more information.  Do "shells -?" to see the
  10.  *     additional parameters which can be varied (listed at the end).
  11.  *
  12.  * Author:  Eric Haines, 3D/Eye, Inc.
  13.  *
  14.  * Modified:  Antonio Costa, INESC
  15.  *     Changed lib_get_opts to shells_get_opts
  16.  *     Corrected bug with light source definition
  17.  *     Changed several vars from COORD4 to COORD3
  18.  *
  19.  * Size factor determines the number of objects output.
  20.  *      Total objects = 180*(2**SF) spheres
  21.  *
  22.  *      Size factor     # spheres    # squares
  23.  *           1              360           1
  24.  *           2              720           1
  25.  *           3             1440           1
  26.  *           4             2880           1
  27.  *           5             5760           1
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <math.h>
  32. #include "def.h"
  33. #include "lib.h"
  34.  
  35. /* These may be read from the command line */
  36. static int size_factor      = 5;
  37. static int raytracer_format = OUTPUT_RT_DEFAULT;
  38. static int output_format    = OUTPUT_CURVES;
  39.  
  40.  
  41. static  double  fgamma = 1.0 ;  /* 0.01 to 3 */
  42. static  double  alpha = 0.0 ;   /* > 1 - 1.1 is good */
  43. static  double  beta = -2.0 ;   /* ~ -2 */
  44. static  double  a = 0.15 ;      /* exponent constant */
  45. static  double  k = 1.0 ;       /* relative size */
  46.  
  47.  
  48. static void
  49. shells_show_usage()
  50. {
  51.     show_gen_usage() ;
  52.     fprintf(stderr, "-a alpha - alpha value (0 to 1.1 is good)\n");
  53.     fprintf(stderr, "-b beta - beta value (-2 is good)\n");
  54.     fprintf(stderr, "-g gamma - gamma value (0.01 to 3 is good)\n");
  55.     fprintf(stderr, "-e exponent - exponent value (0.15 is good)\n");
  56. }
  57.  
  58. static int
  59. shells_get_opts( argc, argv, p_size, p_rdr, p_curve )
  60. int     argc ;
  61. char    *argv[] ;
  62. int     *p_size, *p_rdr, *p_curve ;
  63. {
  64. int num_arg ;
  65. int val ;
  66. double fval ;
  67.  
  68.     num_arg = 0 ;
  69.  
  70.     while ( ++num_arg < argc ) {
  71.     if ( (*argv[num_arg] == '-') || (*argv[num_arg] == '/') ) {
  72.         switch( argv[num_arg][1] ) {
  73.         case 'g':       /* gamma */
  74.             if ( ++num_arg < argc ) {
  75.             sscanf( argv[num_arg], "%lf", &fval ) ;
  76.             if ( fval < 0.0 ) {
  77.                 fprintf( stderr,
  78.                     "bad gamma value %lf given\n",fval);
  79.                 shells_show_usage();
  80.                 return( TRUE ) ;
  81.             }
  82.             fgamma = fval ;
  83.             } else {
  84.             fprintf( stderr, "not enough args for -g option\n" ) ;
  85.             shells_show_usage();
  86.             return( TRUE ) ;
  87.             }
  88.             break ;
  89.         case 'a':       /* alpha */
  90.             if ( ++num_arg < argc ) {
  91.             sscanf( argv[num_arg], "%lf", &alpha ) ;
  92.             } else {
  93.             fprintf( stderr, "not enough args for -a option\n" ) ;
  94.             shells_show_usage();
  95.             return( TRUE ) ;
  96.             }
  97.             break ;
  98.         case 'b':       /* beta */
  99.             if ( ++num_arg < argc ) {
  100.             sscanf( argv[num_arg], "%lf", &beta ) ;
  101.             } else {
  102.             fprintf( stderr, "not enough args for -b option\n" ) ;
  103.             shells_show_usage();
  104.             return( TRUE ) ;
  105.             }
  106.             break ;
  107.         case 'e':       /* exponent selection */
  108.             if ( ++num_arg < argc ) {
  109.             sscanf( argv[num_arg], "%lf", &a ) ;
  110.             } else {
  111.             fprintf( stderr, "not enough args for -e option\n" ) ;
  112.             shells_show_usage();
  113.             return( TRUE ) ;
  114.             }
  115.             break ;
  116.  
  117.         case 's':       /* size selection */
  118.             if ( ++num_arg < argc ) {
  119.             sscanf( argv[num_arg], "%d", &val ) ;
  120.             if ( val < 1 ) {
  121.                 fprintf( stderr,
  122.                     "bad size value %d given\n",val);
  123.                 shells_show_usage();
  124.                 return( TRUE ) ;
  125.             }
  126.             *p_size = val ;
  127.             } else {
  128.             fprintf( stderr, "not enough args for -s option\n" ) ;
  129.             shells_show_usage();
  130.             return( TRUE ) ;
  131.             }
  132.             break ;
  133.         case 'c':       /* true curve output */
  134.             *p_curve = OUTPUT_CURVES ;
  135.             break ;
  136.         case 't':       /* tessellated curve output */
  137.             *p_curve = OUTPUT_PATCHES ;
  138.             break ;
  139.         case 'r':       /* renderer selection */
  140.             if ( ++num_arg < argc ) {
  141.             sscanf( argv[num_arg], "%d", &val ) ;
  142.             if ( val < OUTPUT_VIDEO || val >= OUTPUT_DELAYED ) {
  143.                 fprintf( stderr,
  144.                     "bad renderer value %d given\n",val);
  145.                 shells_show_usage();
  146.                 return( TRUE ) ;
  147.             }
  148.             *p_rdr = val ;
  149.             } else {
  150.             fprintf( stderr, "not enough args for -r option\n" ) ;
  151.             shells_show_usage();
  152.             return( TRUE ) ;
  153.             }
  154.             break ;
  155.         default:
  156.             fprintf( stderr, "unknown argument -%c\n",
  157.                 argv[num_arg][1] ) ;
  158.             shells_show_usage();
  159.             return( TRUE ) ;
  160.         }
  161.     } else {
  162.         fprintf( stderr, "unknown argument %s\n",
  163.             argv[num_arg] ) ;
  164.         shells_show_usage();
  165.         return( TRUE ) ;
  166.     }
  167.     }
  168.     return( FALSE ) ;
  169. }
  170.  
  171. int
  172. main(argc,argv)
  173. int     argc ;
  174. char    *argv[] ;
  175. {
  176. double  r,angle ;
  177. long    i, steps ;
  178. COORD3  back_color, obj_color ;
  179. COORD3  from, at, up ;
  180. COORD4  light ;
  181. COORD4  sphere;
  182.  
  183.     PLATFORM_INIT(SPD_SHELLS);
  184.  
  185.     /* Start by defining which raytracer we will be using */
  186.     if ( shells_get_opts( argc, argv,
  187.             &size_factor, &raytracer_format, &output_format ) ) {
  188.     return EXIT_FAIL;
  189.     }
  190.     if ( lib_open( raytracer_format, "Shells.out" ) ) {
  191.     return EXIT_FAIL;
  192.     }
  193.  
  194.     lib_set_polygonalization(2, 2);
  195.  
  196.     /* output background color - UNC sky blue */
  197.     /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */
  198.     SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ;
  199.     lib_output_background_color( back_color ) ;
  200.  
  201.     /* output viewpoint */
  202.     SET_COORD3( from, -6.0, -60.0, 35.0 ) ;
  203.     SET_COORD3( at, 0.0, 8.0, -15.0 ) ;
  204.     SET_COORD3( up, 0.0, 0.0, 1.0 ) ;
  205.     lib_output_viewpoint( from, at, up, 45.0, 1.0, 0.5, 512, 512 ) ;
  206.  
  207.     /* output light sources */
  208.     SET_COORD4( light, -100.0, -100.0, 100.0, 1.0 ) ;
  209.     lib_output_light( light ) ;
  210.  
  211.     /* set up sphere color */
  212.     SET_COORD3( obj_color, 1.0, 0.8, 0.4 ) ;
  213.     lib_output_color( NULL, obj_color, 0.0, 0.8, 0.2, 0.5, 5.0, 0.0, 1.0 ) ;
  214.  
  215.     steps = 180.0 * pow( 2.0, (double)size_factor ) ;
  216.     for ( i = -steps*2/3; i <= steps/3 ; ++i ) {
  217.     PLATFORM_MULTITASK();
  218.  
  219.     angle = 3.0 * 6.0 * PI * (double)i / (double)steps ;
  220.     r = k * exp( a * angle ) ;
  221.     sphere[X] = r * sin( angle ) ;
  222.     sphere[Y] = r * cos( angle ) ;
  223.     if ( alpha > 0.0 ) {
  224.         /* alternate formula: z = alpha * angle */
  225.         sphere[Z] = alpha * angle ;
  226.     } else {
  227.         sphere[Z] = beta * r ;
  228.     }
  229.     sphere[W] = r / fgamma ;
  230.     lib_output_sphere( sphere, output_format ) ;
  231.     }
  232.  
  233.     lib_close();
  234.  
  235.     PLATFORM_SHUTDOWN();
  236.     return EXIT_SUCCESS;
  237. }
  238.